﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace wielomiany {
	/// <summary>
	/// klasa liczb zespolonych
	/// </summary>
	class Complex { 
		#region pola, właściwości i konstruktory
		private double re;
		private double im;
		/// <summary>
		/// informacja, czy liczba jest poprawna, pozwala zwrócić informację o błędnym wyniku
		/// </summary>
		private bool isProper;
		/// <summary>
		/// część rzeczywista liczby zespolonej
		/// </summary>
		public double Re {
			get {
				return re;
			}
			set {
				re = value;
				this.isProper = true;
			}
		}
		/// <summary>
		/// część urojona liczby zespolonej
		/// </summary>
		public double Im {
			get {
				return im;
			}
			set {
				im = value;
				isProper = true;
			}
		}
		/// <summary>
		/// informacja o poprawności liczby zespolonej
		/// </summary>
		public bool IsProper {
			get {
				return this.isProper;
			}
		}
		/// <summary>
		/// kosntruktor kopiujący
		/// </summary>
		/// <param name="y">kopiowana liczba zespolona</param>
		public Complex (Complex y) {
			re = y.re;
			im = y.im;
			this.isProper = true;
		}
		/// <summary>
		/// konstruktor domyślny, tak utworzona liczba zespolona rzutowana jest do false
		/// </summary>
		public Complex() {
			re = 0;
			im = 0;
			this.isProper = false;
		}
		/// <summary>
		/// konstruktor, w któym można ustawić wartości Re i Im
		/// </summary>
		/// <param name="r">część rzeczywista</param>
		/// <param name="i">część urojona, paramter opcjonalny, domyślnie 0</param>
		public Complex (double r, double i=0) {
			re = r;
			im = i;
			this.isProper = true;
		}
		#endregion
		#region rzutowania i konwersje
		/// <summary>
		/// domyślne rzutowanie do stringa
		/// </summary>
		/// <returns>zwraca zapis liczby zespolonej</returns>
		public override string ToString () {
			return "" + re +znakIm() + im + "i";
		}
		/// <summary>
		/// rzutowanie do stringa
		/// </summary>
		/// <param name="n">ilość wyświetlanych miejsc po przecinku</param>
		/// <returns>zwraca zapis liczby zespolonej</returns>
		public string ToString (int n) {
			return "" + re.ToString("f"+n) + znakIm() + im.ToString("f"+n) + "i";
		}
		/// <summary>
		/// rzutowanie do stringa
		/// </summary>
		/// <param name="f">format wyświetlania liczb</param>
		/// <returns>zwraca zapis liczby zespolonej</returns>
		public string ToString (string f) {
			return "" + re.ToString(f) + znakIm() + im.ToString(f) + "i";
		}
		/// <summary>
		/// niejawny operator rzutowania do typu bool
		/// </summary>
		/// <param name="x">liczba zespolona do rzutowania</param>
		/// <returns>zwraca informację o poprawności liczby</returns>
		public static implicit operator bool (Complex x) {
			return x.isProper;
		} 
		#endregion
		#region metody prywatne
		/// <summary>
		/// określa znak części urojonej liczby zespolonej
		/// </summary>
		/// <returns>zwraca string zawierający znak '+' lub '-'</returns>
		private string znakIm () {
			string znak = "";
			if (im >= 0) {
				znak = "+";
			}
			return znak;
		}
		#endregion
		#region metody publiczne i operatory
		#region metody publiczne
		/// <summary>
		/// moduł liczby zespolonej
		/// </summary>
		/// <returns>zwraca liczbę typu double reprezentującą moduł</returns>
		public double module () {
			double modul = 0;
			modul = Math.Sqrt(re*re + im*im);
			return modul;
		}
		/// <summary>
		/// liczba sprzężona
		/// </summary>
		/// <returns>zwraca liczbę zespoloną będącą sprzężeniem danej liczby</returns>
		public Complex couple () {
			return new Complex(this.re, -this.im);
		}
		#endregion
		#region operatory arytmetyczne
		#region sumy
		/// <summary>
		/// suma dwóch liczb zespolonych
		/// </summary>
		/// <param name="x">składnik pierwszy</param>
		/// <param name="y">skłądnik drugi</param>
		/// <returns>zwraca nową liczbę zespoloną będącą sumę podanych</returns>
		public static Complex operator + (Complex x, Complex y) {
			return new Complex(x.re + y.re, x.im + y.im);
		}
		/// <summary>
		/// suma liczby zespolonej i stałej - dodaje stałą do części rzeczywistej
		/// </summary>
		/// <param name="x">liczba zespolona</param>
		/// <param name="y">stała</param>
		/// <returns>zwraca liczbę zespoloną z częścią Re powiększoną o stałą</returns>
		public static Complex operator + (Complex x, double y) {
			return new Complex(x.re + y, x.im);
		}
		/// <summary>
		/// suma liczby zespolonej i stałej - dodaje stałą do części rzeczywistej
		/// </summary>
		/// <param name="y">liczba zespolona</param>
		/// <param name="x">stała</param>
		/// <returns>zwraca liczbę zespoloną z częścią Re powiększoną o stałą</returns>
		public static Complex operator + (double y, Complex x) {
			return x + y;
		}
		#endregion
		#region różnice
		/// <summary>
		/// różnica dwóch liczb zespolonych
		/// </summary>
		/// <param name="x">odjemna</param>
		/// <param name="y">odjemnik</param>
		/// <returns>liczba zespolona stanowiąca różnicę podanych</returns>
		public static Complex operator - (Complex x, Complex y) {
			return new Complex(x.re - y.re, x.im - y.im);
		}
		/// <summary>
		/// różnica liczby zespolonej i stałej
		/// </summary>
		/// <param name="x">liczba zespolona</param>
		/// <param name="y">stała</param>
		/// <returns>zwraca liczbę zespoloną z częścią Re pomniejszoną o stałą</returns>
		public static Complex operator - (Complex x, double y) {
			return new Complex(x.re - y, x.im);
		}
		#endregion
		#region iloczyny
		/// <summary>
		/// iloczyn dwóch liczb zespolonych
		/// </summary>
		/// <param name="x">czynnik</param>
		/// <param name="y">czynnik</param>
		/// <returns>zwraca liczbę zespoloną bedącą iloczynem podanych</returns>
		public static Complex operator * (Complex x, Complex y) {
			return new Complex((x.re * y.re) - (x.im * y.im), (x.re * y.im) + (x.im * y.re));
		}
		/// <summary>
		/// iloczyn liczby zespolonej i stałej
		/// </summary>
		/// <param name="x">liczba zespolona</param>
		/// <param name="y">stała</param>
		/// <returns>zwraca liczbę zespoloną z częściami Re i Im wymnożonymi przez stałą</returns>
		public static Complex operator * (Complex x, double y) {
			return new Complex(x.re * y, x.im * y);
		}
		/// <summary>
		/// iloczyn liczby zespolonej i stałej
		/// </summary>
		/// <param name="x">liczba zespolona</param>
		/// <param name="y">stała</param>
		/// <returns>zwraca liczbę zespoloną z częściami Re i Im wymnożonymi przez stałą</returns>
		public static Complex operator * (double y, Complex x) {
			return x * y;
		}
		#endregion
		#region ilorazy
		/// <summary>
		/// iloraz dwóch liczb zespolonych
		/// </summary>
		/// <param name="x">dzielna</param>
		/// <param name="y">dzielnik</param>
		/// <returns>zwraca liczbę zespoloną będącą ilorazem podanych</returns>
		public static Complex operator / (Complex x, Complex y) {
			if (y.re == 0 && y.im == 0) {
				return new Complex();
			}
			return new Complex(((x.re * y.re + x.im * y.im) / (y.re * y.re + y.im * y.im)), ((x.im * y.re - x.re * y.im) / (y.re * y.re + y.im * y.im)));
		}
		/// <summary>
		/// iloraz liczby zespolonej i stałej
		/// </summary>
		/// <param name="x">liczba zespolona</param>
		/// <param name="y">stała</param>
		/// <returns>zwraca liczbę zespoloną z częściami Re i Im podzielonymi przez stałą y,
		/// w przypadku stałej równej 0 zwraca pustą liczbę zespoloną rzutowaną do wartości false
		/// </returns>
		public static Complex operator / (Complex x, double y) {
			if (y != 0) {
				return new Complex(x.re / y, x.im / y);
			} else {
				return new Complex();
			}
		}
		#endregion
		#endregion
		#endregion
	}
}
